/*
 * #%L
 * SwiftUICommonUtilities
 * $Id:$
 * $HeadURL:$
 * %%
 * Copyright (C) 2011 - 2012 Linkwithweb
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public 
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/gpl-3.0.html>.
 * #L%
 */
/**
 * 
 */
package com.linkwithweb.products.swiftui.context;

import java.security.KeyPair;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList;

import javax.servlet.ServletContext;

import org.springframework.jdbc.core.JdbcTemplate;

import com.linkwithweb.products.swiftui.utils.FreeMarkerEngine;

/**
 * This common Context Object Used through out the applicationt to deal with all
 * kinds of context objects. Note :- We dont maintain Session variables in this
 * Framework.
 * 
 * All DB Resources are Configured Per request Basis
 * 
 * @author ashwin
 * 
 */
public class SystemContext {

	private ServletContext servletContext = null;

	private ThreadLocal<RequestContext> requestContext = new ThreadLocal<RequestContext>();

	private static SystemContext systemContext = new SystemContext();

	private String basePath = "";

	private String frameworkSchema = "AUTOMATA";

	private ThreadLocal<UserContext> userContext = new ThreadLocal<UserContext>();

	private KeyPair keys = null;

	private Map<String, String> loggedInUsers = new HashMap<String, String>();

	private Map<String, JdbcTemplate> dataSourceMapping = new ConcurrentHashMap<String, JdbcTemplate>();

	private Map<String, String> refreshTableMap = new HashMap<String, String>();

	private Map<String, DBUpdateStatement> approvalMap = new HashMap<String, DBUpdateStatement>();

	Map<String, List<String>> clientNameToErrorListMap = new HashMap<String, List<String>>();

	ThreadLocal<String> clientName = new ThreadLocal<String>();

	ThreadLocal<String> uniqueMessage = new ThreadLocal<String>();

	private Map<String, String> statusMessageMap = new HashMap<String, String>();

	private Map<String, String> sqlExportMap = new HashMap<String, String>();
	
	private static Queue<AsyncDataContainer> concurrentLinkedQueue = new ConcurrentLinkedQueue<AsyncDataContainer>();
	/**
	 * @return
	 */
	public String getUserId() {
		String userId = "${GlobalContext.requestContext.requestWrapper.userId}";
		try {
			userId = FreeMarkerEngine.getInstance().evaluateString(userId);
		} catch (Exception e) {
		}
		return userId;
	}

	/**
	 * 
	 */
	private SystemContext() {
		Locale locale = Locale.getDefault();
		System.out.println("Before setting, Locale is = " + locale);
		// Setting default locale
		locale = Locale.US;
		Locale.setDefault(locale);
		System.out.println("After setting, Locale is = " + locale);
	}

	/**
	 * @return
	 */
	public static SystemContext getInstance() {
		return systemContext;
	}

	/**
	 * @return the requestContext
	 */
	public RequestContext getRequestContext() {
		return requestContext.get();
	}

	/**
	 * @param requestContext
	 *            the requestContext to set
	 */
	public void setRequestContext(RequestContext requestContext) {
		this.requestContext.set(requestContext);
	}

	/**
	 * @return the SystemContext
	 */
	public static SystemContext getSystemContext() {
		return systemContext;
	}

	/**
	 * @param SystemContext
	 *            the SystemContext to set
	 */
	public static void setSystemContext(SystemContext sysContext) {
		systemContext = sysContext;
	}

	/**
	 * @return the servletContext
	 */
	public ServletContext getServletContext() {
		return servletContext;
	}

	/**
	 * @param servletContext
	 *            the servletContext to set
	 */
	public void setServletContext(ServletContext servletContext) {
		this.servletContext = servletContext;
	}

	/**
	 * @return the basePath
	 */
	public String getBasePath() {
		return basePath;
	}

	/**
	 * @param basePath
	 *            the basePath to set
	 */
	public void setBasePath(String basePath) {
		this.basePath = basePath;
	}

	/**
	 * @return the frameworkSchema
	 */
	public String getFrameworkSchema() {
		return frameworkSchema;
	}

	/**
	 * @param frameworkSchema
	 *            the frameworkSchema to set
	 */
	public void setFrameworkSchema(String frameworkSchema) {
		this.frameworkSchema = frameworkSchema;
	}

	/**
	 * @return the userContext
	 */
	public UserContext getUserContext() {
		return userContext.get();
	}

	/**
	 * @param userContext
	 *            the userContext to set
	 */
	public void setUserContext(UserContext userContext) {
		this.userContext.set(userContext);
	}

	/**
	 * @return the keys
	 */
	public KeyPair getKeys() {
		return keys;
	}

	/**
	 * @param keys
	 *            the keys to set
	 */
	public void setKeys(KeyPair keys) {
		this.keys = keys;
	}

	/**
	 * @return the loggedInUsers
	 */
	public Map<String, String> getLoggedInUsers() {
		return loggedInUsers;
	}

	/**
	 * @param loggedInUsers
	 *            the loggedInUsers to set
	 */
	public void setLoggedInUsers(Map<String, String> loggedInUsers) {
		this.loggedInUsers = loggedInUsers;
	}

	/**
	 * @return the dataSourceMapping
	 */
	public Map<String, JdbcTemplate> getDataSourceMapping() {
		return dataSourceMapping;
	}

	/**
	 * @param dataSourceMapping
	 *            the dataSourceMapping to set
	 */
	public void setDataSourceMapping(Map<String, JdbcTemplate> dataSourceMapping) {
		this.dataSourceMapping = dataSourceMapping;
	}

	/**
	 * @return the approvalMap
	 */
	public Map<String, DBUpdateStatement> getApprovalMap() {
		return approvalMap;
	}

	/**
	 * @param approvalMap
	 *            the approvalMap to set
	 */
	public void setApprovalMap(Map<String, DBUpdateStatement> approvalMap) {
		this.approvalMap = approvalMap;
	}

	/**
	 * @return the refreshTableMap
	 */
	public Map<String, String> getRefreshTableMap() {
		return refreshTableMap;
	}

	/**
	 * @param refreshTableMap
	 *            the refreshTableMap to set
	 */
	public void setRefreshTableMap(Map<String, String> refreshTableMap) {
		this.refreshTableMap = refreshTableMap;
	}

	/**
	 * @return the clientNameToErrorListMap
	 */
	public Map<String, List<String>> getClientNameToErrorListMap() {
		return clientNameToErrorListMap;
	}

	/**
	 * @param clientNameToErrorListMap
	 *            the clientNameToErrorListMap to set
	 */
	public void setClientNameToErrorListMap(Map<String, List<String>> clientNameToErrorListMap) {
		this.clientNameToErrorListMap = clientNameToErrorListMap;
	}

	/**
	 * @return the clientName
	 */
	public ThreadLocal<String> getClientName() {
		return clientName;
	}

	/**
	 * @param clientName
	 *            the clientName to set
	 */
	public void setClientName(ThreadLocal<String> clientName) {
		this.clientName = clientName;
	}

	public synchronized List<String> getMessages() {
		return clientNameToErrorListMap.get(clientName.get());
	}

	public synchronized void resetErrorList() {
		clientNameToErrorListMap.put(clientName.get(), new CopyOnWriteArrayList<String>(new ArrayList<String>()));
	}

	/**
	 * @return the uniqueMessage
	 */
	public ThreadLocal<String> getUniqueMessage() {
		return uniqueMessage;
	}

	/**
	 * @param uniqueMessage
	 *            the uniqueMessage to set
	 */
	public void setUniqueMessage(ThreadLocal<String> uniqueMessage) {
		this.uniqueMessage = uniqueMessage;
	}

	/**
	 * @return the sqlExportMap
	 */
	public Map<String, String> getSqlExportMap() {
		return sqlExportMap;
	}

	/**
	 * @param sqlExportMap
	 *            the sqlExportMap to set
	 */
	public void setSqlExportMap(Map<String, String> sqlExportMap) {
		this.sqlExportMap = sqlExportMap;
	}

	/**
	 * @return the statusMessageMap
	 */
	public Map<String, String> getStatusMessageMap() {
		return statusMessageMap;
	}

	/**
	 * @param statusMessageMap
	 *            the statusMessageMap to set
	 */
	public void setStatusMessageMap(Map<String, String> statusMessageMap) {
		this.statusMessageMap = statusMessageMap;
	}

	/**
	 * @param message
	 */
	public void putStatusMessage(String message) {
		this.statusMessageMap.put(getClientName().get(), message);
	}

	/**
	 * @return
	 */
	public String getStatusMessage() {
		return this.statusMessageMap.get(getClientName().get());
	}

	/**
	 * @return the concurrentLinkedQueue
	 */
	public Queue<AsyncDataContainer> getConcurrentLinkedQueue() {
		return concurrentLinkedQueue;
	}

	/**
	 * @param concurrentLinkedQueue the concurrentLinkedQueue to set
	 */
	public void setConcurrentLinkedQueue(Queue<AsyncDataContainer> concurrentLinkedQueue) {
		SystemContext.concurrentLinkedQueue = concurrentLinkedQueue;
	}
	
	

}
